package cn.xdf.docscan

import android.content.Context
import android.graphics.Bitmap
import android.util.Log
import android.graphics.PointF
import cn.xdf.docscan.ui.DocOverlay
import cn.xdf.docscan.ui.QuadOverlay

/**
 * DocScanner主控制器
 * 整合所有组件，实现完整的文档扫描功能
 */
    class DocScannerController private constructor(
    private val context: Context,
    private val quadOverlay: QuadOverlay?,
    private val docOverlay: DocOverlay?,
    private val externalCamera: Any?,
    private val autoCaptureEnabled: Boolean,
        private val autoCaptureStableMs: Long
) {
    
    companion object {
        private const val TAG = "DocScannerController"
    }
    
    // 核心组件
    private var docScannerComponents: DocScannerInitializer.DocScannerComponents? = null
    private lateinit var inputProcessor: InputProcessor
    private lateinit var outputProcessor: OutputProcessor
    private lateinit var stateMachine: DetectionStateMachine
    
    // 时间戳管理
    private var timestampCounter = 0L
    private var originalFrame: Bitmap? = null
    private var imageTransform: ImageTransformationInfo = ImageTransformationInfo(android.graphics.Matrix(), 0, 0)
    private val detectionSmoother = DetectionSmoother()
    private var lastStableStartMs: Long = 0L
    private var lastAcceptedWasStable: Boolean = false
    private var pendingAutoCaptured: Boolean = false
    private var cachedCroppedImages: List<Bitmap> = emptyList()
    private var cachedOriginalImage: Bitmap? = null

        // 覆盖层最近一次数据（可选缓存）
        private var lastQuadDetections: List<QuadOverlay.Detection> = emptyList()
    
    // 回调接口
    interface DocScannerCallback {
        fun onInitialized()
        fun onDetectionStarted()
        fun onDetectionResult(detections: List<DetectionStateMachine.Detection>)
        fun onCroppedFramesReceived(bitmaps: List<Bitmap>)
        fun onOriginalFrameReceived(bitmap: Bitmap)
        fun onCaptureResult(captured: List<Bitmap>)
        fun onRectifiedBitmapReady(bitmap: Bitmap) {}
        fun onError(error: String)
    }
    
    /**
     * 更新图像到预览的坐标变换矩阵
     */
    fun updateImageTransform(
        imageWidth: Int,
        imageHeight: Int,
        rotationDegrees: Int,
        previewWidth: Int,
        previewHeight: Int,
        cropLeft: Int,
        cropTop: Int,
        cropRight: Int,
        cropBottom: Int,
    ) {
        try {
            val srcW = (cropRight - cropLeft).toFloat()
            val srcH = (cropBottom - cropTop).toFloat()
            val srcCx = cropLeft + srcW / 2f
            val srcCy = cropTop + srcH / 2f

            val previewW = previewWidth.toFloat()
            val previewH = previewHeight.toFloat()

            // 先将坐标从裁剪区域平移到原点
            val m = android.graphics.Matrix()
            m.postTranslate(-srcCx, -srcCy)
            // 旋转
            val rot = ((rotationDegrees % 360) + 360) % 360
            if (rot != 0) m.postRotate(rot.toFloat())
            // 旋转后尺寸
            val rw = if (rot == 90 || rot == 270) srcH else srcW
            val rh = if (rot == 90 || rot == 270) srcW else srcH
            // centerCrop 等比缩放
            val scale = maxOf(previewW / rw, previewH / rh)
            m.postScale(scale, scale)
            // 平移到预览中心
            m.postTranslate(previewW / 2f, previewH / 2f)

            imageTransform = ImageTransformationInfo(m, imageWidth, imageHeight)
            Log.d(TAG, "更新变换矩阵: img=${imageWidth}x${imageHeight}, rot=$rotationDegrees, pv=${previewWidth}x${previewHeight}, crop=[$cropLeft,$cropTop,$cropRight,$cropBottom], scale=$scale")
        } catch (e: Exception) {
            Log.e(TAG, "更新图像变换失败", e)
        }
    }

    private var callback: DocScannerCallback? = null
    
    /**
     * 初始化DocScanner
     */
    fun initialize(callback: DocScannerCallback) {
        this.callback = callback
        
        try {
            Log.d(TAG, "开始初始化DocScanner...")
            
            // 1. 初始化核心组件
            docScannerComponents = DocScannerInitializer.initialize(context)
            
            // 2. 创建输入处理器
            inputProcessor = InputProcessor(
                docScannerComponents!!.graph,
                docScannerComponents!!.packetCreator
            )
            
            // 3. 创建输出处理器
            outputProcessor = OutputProcessor()
            
            // 4. 创建状态机
            stateMachine = DetectionStateMachine()
            
            // 5. 设置输出回调
            outputProcessor.setupOutputCallbacks(
                docScannerComponents!!.graph,
                object : OutputProcessor.DocScannerCallback {
                    override fun onDetectionResult(detectionData: ByteArray, timestamp: Long) {
                        handleDetectionResult(detectionData)
                    }
                    
                    override fun onCroppedFramesResult(bitmaps: List<Bitmap>, timestamp: Long) {
                        handleCroppedFramesResult(bitmaps)
                    }
                    
                    override fun onOriginalFrameResult(bitmap: Bitmap, timestamp: Long) {
                        handleOriginalFrameResult(bitmap)
                    }
                }
            )
            
            // 6. 设置状态机监听器
            stateMachine.addStateListener(object : DetectionStateMachine.StateListener {
                override fun onStateChanged(oldState: DetectionStateMachine.DetectionState, newState: DetectionStateMachine.DetectionState) {
                    handleStateChanged(oldState, newState)
                }
                
                override fun onDetectionResult(detections: List<DetectionStateMachine.Detection>) {
                    handleDetectionResult(detections)
                }
                
                override fun onCaptureResult(croppedImages: List<Bitmap>, originalImage: Bitmap?) {
                    handleCaptureResult(croppedImages, originalImage)
                }
            })
            
            // 7. 启动Graph
            docScannerComponents!!.graph.startRunningGraph()
            
            Log.d(TAG, "✅ DocScanner初始化完成")
            callback.onInitialized()
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ DocScanner初始化失败", e)
            callback.onError("初始化失败: ${e.message}")
        }
    }
    
    /**
     * 处理Bitmap输入
     */
    fun processBitmap(bitmap: Bitmap) {
        try {
            val timestamp = getNextTimestamp()
            Log.d(TAG, "处理Bitmap输入，时间戳: $timestamp")
            
            // 开始检测状态
            stateMachine.startDetection()
            
            // 处理输入
            inputProcessor.processBitmap(bitmap, timestamp)
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 处理Bitmap失败", e)
            callback?.onError("处理输入失败: ${e.message}")
        }
    }
    
    /**
     * 处理检测结果
     */
    private fun handleDetectionResult(detectionData: ByteArray) {
        try {
            Log.d(TAG, "处理检测结果，数据大小: ${detectionData.size} bytes")
            
            // 更新状态机
            stateMachine.handleDetectionResult(detectionData)
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 处理检测结果失败", e)
        }
    }
    
    /**
     * 处理裁剪帧结果
     */
    private fun handleCroppedFramesResult(bitmaps: List<Bitmap>) {
        try {
            Log.d(TAG, "处理裁剪帧结果，图像数量: ${bitmaps.size}")
            
            // 更新状态机
            // 无论状态为何，均缓存最近一帧裁剪结果，避免竞态导致缓存为空
            cachedCroppedImages = bitmaps
            
            // 通知UI更新
            callback?.onCroppedFramesReceived(bitmaps)
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 处理裁剪帧失败", e)
        }
    }
    
    /**
     * 处理原始帧结果
     */
    private fun handleOriginalFrameResult(bitmap: Bitmap) {
        try {
            Log.d(TAG, "处理原始帧结果，图像尺寸: ${bitmap.width}x${bitmap.height}")
            
            // 保存原始图像
            originalFrame = bitmap
            cachedOriginalImage = bitmap
            
            // 更新状态机
            val currentState = stateMachine.getCurrentState()
            if (currentState is DetectionStateMachine.DetectionState.Captured) {
                // 不主动触发回调，等待用户 capture() 或自动捕获
            }
            
            // 通知UI更新
            callback?.onOriginalFrameReceived(bitmap)
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 处理原始帧失败", e)
        }
    }
    
    /**
     * 处理状态变化
     */
    private fun handleStateChanged(oldState: DetectionStateMachine.DetectionState, newState: DetectionStateMachine.DetectionState) {
        Log.d(TAG, "状态变化: ${oldState::class.simpleName} -> ${newState::class.simpleName}")
        
        when (newState) {
            is DetectionStateMachine.DetectionState.Detecting -> {
                callback?.onDetectionStarted()
            }
            is DetectionStateMachine.DetectionState.Error -> {
                callback?.onError("检测过程中发生错误")
            }
            else -> {}
        }
    }
    
    /**
     * 处理检测结果
     */
    private fun handleDetectionResult(detections: List<DetectionStateMachine.Detection>) {
        Log.d(TAG, "检测到 ${detections.size} 个文档")
        
        // 更新UI
        updateDetectionUI(detections)
        
        // 通知回调
        callback?.onDetectionResult(detections)
    }
    
    /**
     * 处理捕获结果
     */
    private fun handleCaptureResult(croppedImages: List<Bitmap>, originalImage: Bitmap?) {
        Log.d(TAG, "捕获完成，裁剪图像: ${croppedImages.size} 个")
        callback?.onCaptureResult(if (croppedImages.isNotEmpty()) croppedImages else emptyList())
    }
    
    /**
     * 更新检测UI
     */
    private fun updateDetectionUI(detections: List<DetectionStateMachine.Detection>) {
        try {
            Log.d(TAG, "🔄 开始更新检测UI，检测数量: ${detections.size}")
            
            // 打印检测详情
            detections.forEachIndexed { index, detection ->
                Log.d(TAG, "📊 检测${index + 1}: 置信度=${detection.confidence}, 边界=${detection.bounds}")
                detection.corners.forEachIndexed { cornerIndex, corner ->
                    Log.d(TAG, "  角点${cornerIndex + 1}: (${corner.x}, ${corner.y})")
                }
            }
            
            // 确保在主线程上更新UI
            val handler = android.os.Handler(android.os.Looper.getMainLooper())
            handler.post {
                try {
                    Log.d(TAG, "🎨 在主线程更新UI")
                    
                    // 将归一化坐标通过矩阵映射到预览坐标
                    val mappedDetections = detections.mapNotNull { detection ->
                        val pts = FloatArray(8)
                        for (i in 0 until 4) {
                            pts[i * 2] = detection.corners[i].x * imageTransform.imageWidth
                            pts[i * 2 + 1] = detection.corners[i].y * imageTransform.imageHeight
                        }
                        imageTransform.transformationMatrix.mapPoints(pts)
                        val mappedCorners = listOf(
                            android.graphics.PointF(pts[0], pts[1]),
                            android.graphics.PointF(pts[2], pts[3]),
                            android.graphics.PointF(pts[4], pts[5]),
                            android.graphics.PointF(pts[6], pts[7])
                        )
                        val accept = detectionSmoother.accept(
                            mappedCorners,
                            (quadOverlay?.width ?: docOverlay?.width ?: 0),
                            (quadOverlay?.height ?: docOverlay?.height ?: 0)
                        )
                        if (!accept) return@mapNotNull null
                        val filtered = mappedCorners
                        cn.xdf.docscan.view.QuadrilateralView.Detection(
                            corners = filtered,
                            confidence = detection.confidence
                        )
                    }
                    
                    Log.d(TAG, "📐 更新四边形视图，检测数量: ${mappedDetections.size}")
                    if (mappedDetections.isNotEmpty()) {
                        // 当前帧有有效检测：更新并缓存
                        val quadDetections = mappedDetections.map { QuadOverlay.Detection(it.corners, it.confidence) }
                        lastQuadDetections = quadDetections
                        quadOverlay?.updateDetection(quadDetections)

                        val detection = mappedDetections.first()
                        // 如有原始帧缓存，可尝试透视矫正后回调给上层
                        try {
                            val ori = originalFrame
                            if (ori != null) {
                                val rectified = cn.xdf.docscan.util.ImageWarp.warpQuadToRect(
                                    ori,
                                    detection.corners
                                )
                                if (rectified != null) {
                                    callback?.onRectifiedBitmapReady(rectified)
                                }
                            }
                        } catch (e: Exception) {
                            Log.w(TAG, "Rectify failed", e)
                        }
                        // 不再更新 DocumentOverlayView，避免重复绘制
                        // 自动捕获
                        if (autoCaptureEnabled) {
                            val now = System.currentTimeMillis()
                            if (!lastAcceptedWasStable) {
                                lastStableStartMs = now
                                lastAcceptedWasStable = true
                            } else {
                                if (!pendingAutoCaptured && now - lastStableStartMs >= autoCaptureStableMs) {
                                    pendingAutoCaptured = true
                                    capture()
                                }
                            }
                        }
                    } else {
                        // 无检测：若设备未明显移动，则短时保留上一结果，避免时有时无
                        val now = System.currentTimeMillis()
                        val withinHold = (now - lastStableStartMs) <= 1000L
                        if (withinHold && lastQuadDetections.isNotEmpty()) {
                            quadOverlay?.updateDetection(lastQuadDetections)
                        } else {
                            quadOverlay?.clearDetection()
                            docOverlay?.clearDetection()
                            lastQuadDetections = emptyList()
                            lastAcceptedWasStable = false
                            pendingAutoCaptured = false
                        }
                    }
                    
                    Log.d(TAG, "✅ UI更新完成")
                    
                } catch (e: Exception) {
                    Log.e(TAG, "❌ 主线程UI更新失败", e)
                }
            }
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 更新检测UI失败", e)
        }
    }
    
    /**
     * 获取下一个时间戳
     */
    private fun getNextTimestamp(): Long {
        return ++timestampCounter
    }
    
    /**
     * 释放资源
     */
    fun release() {
        try {
            Log.d(TAG, "释放DocScanner资源...")
            
            // 停止Graph
            docScannerComponents?.graph?.closeAllPacketSources()
            docScannerComponents?.graph?.waitUntilGraphDone()
            
            // 清除状态
            stateMachine.reset()
            detectionSmoother.reset()
            
            // 清除UI
            quadOverlay?.clearDetection()
            docOverlay?.clearDetection()
            
            Log.d(TAG, "✅ DocScanner资源释放完成")
            
        } catch (e: Exception) {
            Log.e(TAG, "❌ 释放资源失败", e)
        }
    }

        fun capture() {
        try {
            Log.d(TAG, "手动触发捕获，缓存图像数量: ${cachedCroppedImages.size}")
            if (cachedCroppedImages.isNotEmpty()) {
                callback?.onCaptureResult(cachedCroppedImages)
                return
            }
            // 回退：若没有裁剪缓存，尝试用最后一次检测四角从原始帧做透视矫正，生成单张图返回
            val ori = originalFrame
            val last = lastQuadDetections.firstOrNull()
            if (ori != null && last != null) {
                val rectified = cn.xdf.docscan.util.ImageWarp.warpQuadToRect(ori, last.corners)
                if (rectified != null) {
                    callback?.onCaptureResult(listOf(rectified))
                    return
                }
            }
            callback?.onCaptureResult(emptyList())
        } catch (e: Exception) {
            Log.e(TAG, "❌ 捕获失败", e)
        }
    }

    fun getLastDetectedCorners(): List<PointF>? {
        return lastQuadDetections.firstOrNull()?.corners
    }

    class Builder(private val context: Context) {
        private var quadOverlay: QuadOverlay? = null
        private var docOverlay: DocOverlay? = null
        private var externalCamera: Any? = null
        private var autoCaptureEnabled: Boolean = false
        private var autoCaptureStableMs: Long = 2000L
            private var overlayHoldMs: Long = 500L

        fun setQuadOverlay(overlay: QuadOverlay?): Builder { this.quadOverlay = overlay; return this }
        fun setDocOverlay(overlay: DocOverlay?): Builder { this.docOverlay = overlay; return this }
        fun setExternalCamera(camera: Any?): Builder { this.externalCamera = camera; return this }
            fun enableAutoCapture(enabled: Boolean, stableMs: Long = 2000L): Builder {
            this.autoCaptureEnabled = enabled
            this.autoCaptureStableMs = stableMs
            return this
        }
            fun setOverlayHoldMs(holdMs: Long): Builder {
                this.overlayHoldMs = holdMs
                return this
            }
        fun build(): DocScannerController {
            return DocScannerController(context, quadOverlay, docOverlay, externalCamera, autoCaptureEnabled, autoCaptureStableMs)
        }
    }
} 